<?php

namespace app\controller\workorder;

use app\BaseController;
use think\facade\Db;
use think\facade\Request;
use think\facade\Validate;
use think\facade\Log;

/**
 * 工单管理
 */
class WorkOrder extends BaseController
{
    /**
     * 获取工单列表
     */
    public function list()
    {
        try {
            $params = Request::param();
            $page = isset($params['page']) && is_numeric($params['page']) ? max(1, (int)$params['page']) : 1;
            $limit = isset($params['limit']) && is_numeric($params['limit']) ? max(1, min(100, (int)$params['limit'])) : 20;
            $category = $params['category'] ?? '';
            $status = $params['status'] ?? '';
            $assigneeId = $params['assignee_id'] ?? '';

            // 验证参数
            if ($status && (!is_numeric($status) || !in_array((int)$status, [1, 2, 3, 4]))) {
                return $this->error('参数错误: 无效的工单状态');
            }

            if ($assigneeId && (!is_numeric($assigneeId) || $assigneeId <= 0)) {
                return $this->error('参数错误: 无效的负责人ID');
            }

            $query = Db::name('work_order')
                ->alias('wo')
                ->field('wo.*, o.order_no, a1.name as assignee_name, a2.name as department_manager_name')
                ->leftJoin('crm_order o', 'wo.order_id = o.id')
                ->leftJoin('admin a1', 'wo.assignee_id = a1.id')
                ->leftJoin('admin a2', 'wo.department_manager_id = a2.id');

            if ($category) {
                $query->where('wo.category', $category);
            }

            if ($status) {
                $query->where('wo.status', $status);
            }

            if ($assigneeId) {
                $query->where('wo.assignee_id', $assigneeId);
            }

            $total = $query->count();
            $list = $query->order('wo.create_time', 'desc')
                ->page($page, $limit)
                ->select();

            return $this->paginate($list ? $list->toArray() : [], $total, (int)$page, (int)$limit);
        } catch (\Exception $e) {
            Log::error('获取工单列表失败: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('获取工单列表失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取工单详情
     */
    public function detail()
    {
        try {
            $id = Request::param('id');
            if (!$id) {
                return $this->error('参数错误');
            }

            $workOrder = Db::name('work_order')
                ->alias('wo')
                ->field('wo.*, o.order_no, o.customer_name, a1.name as assignee_name, a2.name as department_manager_name')
                ->leftJoin('crm_order o', 'wo.order_id = o.id')
                ->leftJoin('admin a1', 'wo.assignee_id = a1.id')
                ->leftJoin('admin a2', 'wo.department_manager_id = a2.id')
                ->where('wo.id', $id)
                ->find();

            if (!$workOrder) {
                return $this->error('工单不存在');
            }

            // 检查数据权限
            if (!$this->checkDataPermission($workOrder)) {
                Log::warning('工单访问权限拒绝: 用户ID = ' . $this->getUserId() . ', 工单ID = ' . $id);
                return $this->error('没有权限访问此数据', 403);
            }

            // 获取进度记录
            $progressList = Db::name('work_order_progress')
                ->where('work_order_id', $id)
                ->order('create_time', 'desc')
                ->select();

            $workOrder['progress_list'] = $progressList ? $progressList->toArray() : [];

            return $this->success($workOrder);
        } catch (\Exception $e) {
            Log::error('获取工单详情失败: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('获取工单详情失败: ' . $e->getMessage());
        }
    }

    /**
     * 分配工单（部长操作）
     */
    public function assign()
    {
        $params = Request::param();
        $userId = $this->getUserId();

        if (!$userId) {
            return $this->error('未登录或登录已过期', 401);
        }

        // 验证参数
        $validate = Validate::rule([
            'work_order_id|工单ID' => 'require|number',
            'assignee_id|分配人ID' => 'require|number',
            'assign_remark|分配备注' => 'max:255' // 可选的分配备注
        ]);

        if (!$validate->check($params)) {
            return $this->error($validate->getError());
        }

        // 检查工单是否存在
        $workOrder = Db::name('work_order')->where('id', $params['work_order_id'])->find();
        if (!$workOrder) {
            return $this->error('工单不存在');
        }
        
        // 检查工单状态是否允许分配
        if ($workOrder['status'] != 1 && $workOrder['status'] != 2) {
            return $this->error('只有待分配或进行中的工单可以重新分配');
        }

        // 检查用户是否是部门经理
        $userInfo = Db::name('admin')->where('id', $userId)->find();
        if (!$userInfo || $userInfo['group_id'] != 2) {
            return $this->error('只有部门经理才能分配工单');
        }
        
        // 验证被分配人是否存在
        $assigneeInfo = Db::name('admin')->where('id', $params['assignee_id'])->find();
        if (!$assigneeInfo) {
            return $this->error('被分配人不存在');
        }

        // 检查部门经理是否有权分配此工单
        if ($userInfo['did'] != $this->getDepartmentByOrder($workOrder['order_id'])) {
            return $this->error('您无权分配此工单');
        }

        $oldAssigneeId = $workOrder['assignee_id'];

        // 使用事务确保数据一致性
        Db::startTrans();
        try {
            // 更新工单分配
            Db::name('work_order')->where('id', $params['work_order_id'])->update([
                'assignee_id' => $params['assignee_id'],
                'status' => 2,  // 进行中
                'start_time' => time(),
                'update_time' => time()
            ]);

            // 记录分配历史
            $this->recordAssignmentHistory(
                $params['work_order_id'],
                $oldAssigneeId,
                $params['assignee_id'],
                $oldAssigneeId ? 'reassign' : 'initial',
                $userId
            );

            // 构建进度内容
            $progressContent = '工单已分配给 ' . $this->getUserName($params['assignee_id']);
            if (!empty($params['assign_remark'])) {
                $progressContent .= '，备注：' . $params['assign_remark'];
            }
            
            // 记录进度
            Db::name('work_order_progress')->insert([
                'work_order_id' => $params['work_order_id'],
                'operator_id' => $userId,
                'operator_name' => $userInfo['name'],
                'progress_type' => 1,
                'old_status' => $workOrder['status'],
                'new_status' => 2,
                'content' => $progressContent,
                'create_time' => time()
            ]);

            // 提交事务
            Db::commit();
            return $this->success([], '分配成功');
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            Log::error('工单分配失败: 工单ID = ' . $params['work_order_id'] . ', 错误: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('分配失败: ' . $e->getMessage());
        }
    }

    /**
     * 添加进度
     */
    public function addProgress()
    {
        $params = Request::param();
        $userId = $this->getUserId();

        if (!$userId) {
            return $this->error('未登录或登录已过期', 401);
        }

        // 验证参数
        $validate = Validate::rule([
            'work_order_id|工单ID' => 'require|number',
            'content|回复内容' => 'require|min:1|max:1000'
        ]);

        if (!$validate->check($params)) {
            return $this->error($validate->getError());
        }

        // 检查工单是否存在
        $workOrder = Db::name('work_order')->where('id', $params['work_order_id'])->find();
        if (!$workOrder) {
            return $this->error('工单不存在');
        }

        // 检查用户是否有权限操作此工单
        if (!$this->checkWorkOrderPermission($workOrder, $userId)) {
            return $this->error('没有权限操作此工单');
        }
        
        // 只有进行中的工单才能添加进度
        if ($workOrder['status'] != 2) {
            return $this->error('只有进行中的工单才能添加进度记录');
        }

        // 使用事务确保数据一致性
        Db::startTrans();
        try {
            // 记录进度
            $progressId = Db::name('work_order_progress')->insertGetId([
                'work_order_id' => $params['work_order_id'],
                'operator_id' => $userId,
                'operator_name' => $this->getUserName($userId),
                'progress_type' => 2,  // 进度添加
                'content' => $params['content'],
                'create_time' => time()
            ]);

            // 提交事务
            Db::commit();
            return $this->success(['id' => $progressId], '添加进度成功');
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            Log::error('添加工单进度失败: 工单ID = ' . $params['work_order_id'] . ', 错误: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('添加进度失败: ' . $e->getMessage());
        }
    }

    /**
     * 更新工单状态
     */
    public function updateStatus()
    {
        $params = Request::param();
        $userId = $this->getUserId();

        if (!$userId) {
            return $this->error('未登录或登录已过期', 401);
        }

        // 验证参数
        $validate = Validate::rule([
            'work_order_id|工单ID' => 'require|number',
            'status|工单状态' => 'require|in:1,2,3,4',
            'remark|备注' => 'max:255' // 可选的备注字段
        ]);

        if (!$validate->check($params)) {
            return $this->error('参数验证失败: ' . $validate->getError());
        }

        // 检查工单是否存在
        $workOrder = Db::name('work_order')->where('id', $params['work_order_id'])->find();
        if (!$workOrder) {
            return $this->error('工单不存在');
        }

        // 检查用户是否有权限操作此工单
        if (!$this->checkWorkOrderPermission($workOrder, $userId)) {
            return $this->error('没有权限操作此工单');
        }
        
        // 验证状态转换是否合法
        if (!$this->isValidStatusTransition($workOrder['status'], $params['status'], $userId)) {
            return $this->error('不允许的状态转换: 从"' . $this->getStatusText($workOrder['status']) . '"到"' . $this->getStatusText($params['status']) . '"');
        }

        $updateData = [
            'status' => $params['status'],
            'update_time' => time()
        ];

        // 如果是完成状态，设置实际结束时间
        if ($params['status'] == 3) {
            $updateData['actual_end_time'] = time();
        }

        // 使用事务确保数据一致性
        Db::startTrans();
        try {
            Db::name('work_order')->where('id', $params['work_order_id'])->update($updateData);

            // 构建进度内容
            $progressContent = '工单状态已更新为 ' . $this->getStatusText($params['status']);
            if (!empty($params['remark'])) {
                $progressContent .= '，备注：' . $params['remark'];
            }
            
            // 记录进度
            Db::name('work_order_progress')->insert([
                'work_order_id' => $params['work_order_id'],
                'operator_id' => $userId,
                'operator_name' => $this->getUserName($userId),
                'progress_type' => 1,
                'old_status' => $workOrder['status'],
                'new_status' => $params['status'],
                'content' => $progressContent,
                'create_time' => time()
            ]);

            // 提交事务
            Db::commit();
            return $this->success([], '状态更新成功');
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            Log::error('更新工单状态失败: 工单ID = ' . $params['work_order_id'] . ', 新状态 = ' . $params['status'] . ', 错误: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('状态更新失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取收到的工单
     */
    public function received()
    {
        try {
            $params = Request::param();
            $page = $params['page'] ?? 1;
            $limit = $params['limit'] ?? 20;
            $status = $params['status'] ?? '';

            $userId = $this->getUserId();
            if (!$userId) {
                return $this->error('未登录或登录已过期', 401);
            }

            $query = Db::name('work_order')
                ->alias('wo')
                ->field('wo.*, o.order_no')
                ->leftJoin('crm_order o', 'wo.order_id = o.id')
                ->where('wo.department_manager_id', $userId);

            if ($status) {
                $query->where('wo.status', $status);
            }

            $total = $query->count();
            $list = $query->order('wo.create_time', 'desc')
                ->page($page, $limit)
                ->select();

            return $this->paginate($list ? $list->toArray() : [], $total, (int)$page, (int)$limit);
        } catch (\Exception $e) {
            Log::error('获取收到的工单失败: 用户ID = ' . $this->getUserId() . ', 错误: ' . $e->getMessage());
            return $this->error('获取收到的工单失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取待分配工单
     */
    public function pending()
    {
        try {
            $params = Request::param();
            $page = $params['page'] ?? 1;
            $limit = $params['limit'] ?? 20;
            $category = $params['category'] ?? '';

            $userId = $this->getUserId();
            if (!$userId) {
                return $this->error('未登录或登录已过期', 401);
            }

            // 检查用户是否为部门经理或超级管理员
            $userInfo = Db::name('admin')->field('group_id')->where('id', $userId)->find();
            if (!$userInfo || !in_array($userInfo['group_id'], [1, 2])) {
                return $this->error('只有部门经理或超级管理员可以查看待分配工单');
            }

            $query = Db::name('work_order')
                ->alias('wo')
                ->field('wo.*, o.order_no, o.customer_name')
                ->leftJoin('crm_order o', 'wo.order_id = o.id')
                ->where('wo.status', 1); // 待分配状态

            // 如果是部门经理，只显示本部门的待分配工单
            if ($userInfo['group_id'] == 2) {
                $userDetail = Db::name('admin')->field('did')->where('id', $userId)->find();
                $departmentId = $userDetail['did'] ?? 0;
                $query->where('o.department_id', $departmentId);
            }

            if ($category) {
                $query->where('wo.category', $category);
            }

            $total = $query->count();
            $list = $query->order('wo.create_time', 'desc')
                ->page($page, $limit)
                ->select();

            return $this->paginate($list ? $list->toArray() : [], $total, (int)$page, (int)$limit);
        } catch (\Exception $e) {
            Log::error('获取待分配工单失败: 用户ID = ' . $this->getUserId() . ', 错误: ' . $e->getMessage());
            return $this->error('获取待分配工单失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取已分配的工单
     */
    public function assigned()
    {
        try {
            $params = Request::param();
            $page = $params['page'] ?? 1;
            $limit = $params['limit'] ?? 20;
            $status = $params['status'] ?? '';

            $userId = $this->getUserId();
            if (!$userId) {
                return $this->error('未登录或登录已过期', 401);
            }

            $query = Db::name('work_order')
                ->alias('wo')
                ->field('wo.*, o.order_no, a.name as department_manager_name')
                ->leftJoin('crm_order o', 'wo.order_id = o.id')
                ->leftJoin('admin a', 'wo.department_manager_id = a.id')
                ->where('wo.assignee_id', $userId);

            if ($status) {
                $query->where('wo.status', $status);
            }

            $total = $query->count();
            $list = $query->order('wo.create_time', 'desc')
                ->page($page, $limit)
                ->select();

            return $this->paginate($list ? $list->toArray() : [], $total, (int)$page, (int)$limit);
        } catch (\Exception $e) {
            Log::error('获取已分配工单失败: 用户ID = ' . $this->getUserId() . ', 错误: ' . $e->getMessage());
            return $this->error('获取已分配工单失败: ' . $e->getMessage());
        }
    }

    /**
     * 检查数据权限
     */
    private function checkDataPermission($workOrder)
    {
        $userId = $this->getUserId();
        if (!$userId) {
            return false;
        }

        $userInfo = Db::name('admin')
            ->field('id, group_id, did')
            ->where('id', $userId)
            ->find();

        if (!$userInfo) {
            return false;
        }

        // 超级管理员
        if ($userInfo['group_id'] == 1) {
            return true;
        }

        // 部门经理
        if ($userInfo['group_id'] == 2) {
            return $userId == $workOrder['department_manager_id'];
        }

        // 交付人员（普通员工）
        return $workOrder['assignee_id'] == $userId;
    }

    /**
     * 检查工单操作权限
     */
    private function checkWorkOrderPermission($workOrder, $userId)
    {
        $userInfo = Db::name('admin')
            ->field('id, group_id')
            ->where('id', $userId)
            ->find();

        // 超级管理员和部门经理都可以操作
        if ($userInfo['group_id'] == 1 || $userInfo['group_id'] == 2) {
            return true;
        }

        // 交付人员只能操作分配给自己的工单
        return $workOrder['assignee_id'] == $userId;
    }

    /**
     * 记录工单分配历史
     */
    private function recordAssignmentHistory($workOrderId, $fromAssigneeId, $toAssigneeId, $type, $operatorId)
    {
        Db::name('work_order_assignment_history')->insert([
            'work_order_id' => $workOrderId,
            'from_assignee_id' => $fromAssigneeId,
            'to_assignee_id' => $toAssigneeId,
            'assignment_type' => $type,
            'operator_id' => $operatorId,
            'create_time' => time()
        ]);
    }

    /**
     * 获取用户姓名
     */
    private function getUserName($userId)
    {
        $user = Db::name('admin')->field('name')->where('id', $userId)->find();
        return $user ? $user['name'] : '未知';
    }

    /**
     * 根据订单获取部门ID
     */
    private function getDepartmentByOrder($orderId)
    {
        $order = Db::name('crm_order')->field('department_id')->where('id', $orderId)->find();
        return $order ? $order['department_id'] : 0;
    }

    /**
     * 获取状态文本
     */
    private function getStatusText($status)
    {
        $statusMap = [
            1 => '待分配',
            2 => '进行中',
            3 => '已完成',
            4 => '已取消'
        ];
        return $statusMap[$status] ?? '未知';
    }
    
    /**
     * 验证状态转换是否合法
     * 状态转换规则：
     * - 待分配(1) 可以转换为 进行中(2) 或 已取消(4)
     * - 进行中(2) 可以转换为 已完成(3) 或 已取消(4)
     * - 已完成(3) 和 已取消(4) 是终态，不能再转换
     */
    private function isValidStatusTransition($oldStatus, $newStatus, $userId)
    {
        // 如果状态没有变化，总是允许的
        if ($oldStatus == $newStatus) {
            return true;
        }
        
        // 定义合法的状态转换规则
        $validTransitions = [
            1 => [2, 4],  // 待分配可以转到进行中或已取消
            2 => [3, 4],  // 进行中可以转到已完成或已取消
            3 => [],       // 已完成是终态
            4 => []        // 已取消是终态
        ];
        
        // 检查是否是合法转换
        if (isset($validTransitions[$oldStatus]) && in_array($newStatus, $validTransitions[$oldStatus])) {
            return true;
        }
        
        // 超级管理员可以强制进行状态转换（紧急情况）
        $userInfo = Db::name('admin')->where('id', $userId)->field('group_id')->find();
        return $userInfo && $userInfo['group_id'] == 1;
    }

    /**
     * 获取工单分配统计概览
     */
    public function assignmentStats()
    {
        try {
            $userId = $this->getUserId();
            if (!$userId) {
                return $this->error('未登录或登录已过期', 401);
            }

            // 检查用户权限（只有管理员和部门经理可以查看统计数据）
            $userInfo = Db::name('admin')->field('group_id')->where('id', $userId)->find();
            if (!$userInfo || !in_array($userInfo['group_id'], [1, 2])) {
                Log::warning('权限不足: 用户ID = ' . $userId . ' 尝试访问统计数据');
                return $this->error('没有权限访问统计数据', 403);
            }

            // 统计各状态工单数量
            $totalAssignments = Db::name('work_order')->count();
            $inProgress = Db::name('work_order')->where('status', 2)->count();
            $completed = Db::name('work_order')->where('status', 3)->count();
            $pending = Db::name('work_order')->where('status', 1)->count();
            $cancelled = Db::name('work_order')->where('status', 4)->count();

            return $this->success([
                'total_assignments' => $totalAssignments,
                'in_progress' => $inProgress,
                'completed' => $completed,
                'pending' => $pending,
                'cancelled' => $cancelled
            ]);
        } catch (\Exception $e) {
            Log::error('获取工单统计数据失败: 用户ID = ' . $this->getUserId() . ', 错误: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('获取统计数据失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取部门工单分配统计
     */
    public function departmentStats()
    {
        try {
            $userId = $this->getUserId();
            if (!$userId) {
                return $this->error('未登录或登录已过期', 401);
            }

            // 检查用户权限（只有管理员可以查看部门统计）
            $userInfo = Db::name('admin')->field('group_id')->where('id', $userId)->find();
            if (!$userInfo || $userInfo['group_id'] != 1) {
                Log::warning('权限不足: 用户ID = ' . $userId . ' 尝试访问部门统计数据');
                return $this->error('只有超级管理员可以查看部门统计数据', 403);
            }

            // 按部门统计工单
            $stats = Db::name('work_order')
                ->alias('wo')
                ->field('d.id as department_id, d.title as department_name,
                        COUNT(wo.id) as total_count,
                        SUM(CASE WHEN wo.status = 1 THEN 1 ELSE 0 END) as pending_count,
                        SUM(CASE WHEN wo.status = 2 THEN 1 ELSE 0 END) as in_progress_count,
                        SUM(CASE WHEN wo.status = 3 THEN 1 ELSE 0 END) as completed_count,
                        SUM(CASE WHEN wo.status = 4 THEN 1 ELSE 0 END) as cancelled_count')
                ->leftJoin('crm_order o', 'wo.order_id = o.id')
                ->leftJoin('department d', 'o.department_id = d.id')
                ->group('d.id, d.title')
                ->select();

            return $this->success($stats ? $stats->toArray() : []);
        } catch (\Exception $e) {
            Log::error('获取部门工单统计失败: 用户ID = ' . $this->getUserId() . ', 错误: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('获取部门统计失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取员工工单分配统计排行
     */
    public function employeeStats()
    {
        try {
            $userId = $this->getUserId();
            if (!$userId) {
                return $this->error('未登录或登录已过期', 401);
            }

            // 检查用户权限（只有管理员和部门经理可以查看员工统计）
            $userInfo = Db::name('admin')->field('group_id')->where('id', $userId)->find();
            if (!$userInfo || !in_array($userInfo['group_id'], [1, 2])) {
                Log::warning('权限不足: 用户ID = ' . $userId . ' 尝试访问员工统计数据');
                return $this->error('没有权限访问员工统计数据', 403);
            }

            // 统计员工分配的工单数量
            $stats = Db::name('work_order')
                ->alias('wo')
                ->field('a.id as employee_id, a.name as employee_name,
                        COUNT(wo.id) as total_count,
                        SUM(CASE WHEN wo.status = 1 THEN 1 ELSE 0 END) as pending_count,
                        SUM(CASE WHEN wo.status = 2 THEN 1 ELSE 0 END) as in_progress_count,
                        SUM(CASE WHEN wo.status = 3 THEN 1 ELSE 0 END) as completed_count')
                ->leftJoin('admin a', 'wo.assignee_id = a.id')
                ->where('wo.assignee_id', '>', 0)  // 只统计已分配的工单
                ->group('a.id, a.name')
                ->order('total_count', 'desc')
                ->limit(10)
                ->select();

            return $this->success([
                'top_employees' => $stats ? $stats->toArray() : []
            ]);
        } catch (\Exception $e) {
            Log::error('获取员工工单统计失败: 用户ID = ' . $this->getUserId() . ', 错误: ' . $e->getMessage() . '\n' . $e->getTraceAsString());
            return $this->error('获取员工统计失败: ' . $e->getMessage());
        }
    }
}
